import java.awt.Component;
import java.awt.DisplayMode;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;

import javax.imageio.ImageIO;
import javax.swing.JFrame;


public class Game{
	
	private LinkedList<Drawable> drawableList;
	private LinkedList<Drawable> attacks;
	private Drawable drawablePlayer;
	private LinkedList<Drawable> drawableStats;
	private int characterNumber;
	private static Display display;
	private final int MIN_DRAWABLE_ITEMS = 1;
	private boolean canPull2 = false;
	private boolean canPull = false;
	private String chat;
	private boolean left,right,up,down,space,B,dark;
	Point center;
	/**
	 * the main loop of the entire game
	 * @param args worthless. Arguments from command line aren't used
	 */
	public static void main(String[] args)
	{
		Game g = new Game();
		ImageStorage storage = new ImageStorage(g);
		GameSettings.setImageStorage(storage);
		storage.loadImages();
		StartThread startUp = new StartThread(g);
		Thread startThread = new Thread(startUp);
		startThread.start();
		while(g.getCharacterNumber() == 200)
		{
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		DBComm comm = new DBComm(g);
		GameSettings.setDBComm(comm);
		Thread thread2 = new Thread(comm);
		thread2.start();
		comm.setCharacterNumber(g.getCharacterNumber());
		display = new Display(g);
		Thread thread = new Thread(display);
		thread.start();
		g.start();
	}

	/**
	 * initializes instance variables
	 */
	public Game()
	{
		chat = "";
		drawableList = new LinkedList<Drawable>();
		drawableStats = new LinkedList<Drawable>();
		left = false;
		right = false;
		up = false;
		down = false;
		dark = false;
		B = false;
		this.center = new Point(50,50);
		attacks = new LinkedList<Drawable>();
		characterNumber = 200;
	}
	/**
	 * gets what the current center of the screen should be
	 * @return the character's current position (center of screen)
	 */
	public Point getCenter()
	{
		return this.center;
	}
	public void addAttack(Drawable d,int length)
	{
		d.setExtra(length);
		attacks.add(d);
	}
	public void clearAttack()
	{
		attacks.clear();
	}
	public void setCharacterNumber(int i)
	{
		this.characterNumber = i;
	}
	public int getCharacterNumber()
	{
		return characterNumber;
	}
	public LinkedList<Drawable> getAttacks()
	{
		try{
			LinkedList<Drawable> ans = new LinkedList<Drawable>();
			ans.addAll(attacks);
			return ans;
		}catch(Exception e){
			System.out.println(e);
		}
		return null;
	}
	/**
	 * starts the game.  Loads player's sprites and starts player thread
	 */
	public void start(){
		while(true)
		{
			GameSettings.getDBComm().newSet();
			if(left == true)
			{
				GameSettings.getDBComm().sendAction("LEFT");
			}
			if(right == true)
			{
				GameSettings.getDBComm().sendAction("RIGHT");
			}
			if(up == true)
			{
				GameSettings.getDBComm().sendAction("UP");
			}
			if(down == true)
			{
				GameSettings.getDBComm().sendAction("DOWN");
			}
			if(space == true)
			{
				GameSettings.getDBComm().sendAction("SPACE");
			}
			else if(B == true)
			{
				GameSettings.getDBComm().sendAction("B");
			}
			//send chat
			if(chat.length() >=1)
			{
				GameSettings.getDBComm().sendChat(chat);
				chat = "";
			}
			GameSettings.getDBComm().completeSet();
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/**
	 * gets the current list of drawable items recieved from DBComm
	 * @return drawableList
	 */
	public LinkedList<Drawable> getDrawableList()
	{
			try{
				LinkedList<Drawable> ans = new LinkedList<Drawable>();
				ans.addAll(drawableList);
				ans.add(drawablePlayer);
				drawableList.clear();
				canPull = false;
				canPull2 = false;
				return ans;
			}catch(Exception e){
				System.out.println(e);
			}
			return null;
	}
	/**
	 * adds drawable items to the list of drawable items.
	 * Enables display to now pull this list, knowing it is now populated
	 * @param d drawable list
	 */
	@SuppressWarnings("unchecked")
	public void addDrawableItems(LinkedList<Drawable> d)
	{
		if(d!=null)
		{
			try{
				
				drawableList.addAll(d);
				canPull = true;
				display.canPaint();
			}
			catch(Exception e)
			{
				System.out.println(e);
			}
			
		}
	}
	public void setDark()
	{
		dark = true;
	}
	public boolean getDark()
	{
		boolean temp = dark;
		dark = false;
		return temp;
	}
	/**
	 * adds a single drawable item it drawableList
	 * @param d drawable item
	 */
	@SuppressWarnings("unchecked")
	public void addDrawableItem(Drawable d)
	{
		//Key key = new Key(0, 1, 0, 0);
		//Sprite sprite = new Sprite(0,0,key);
		//drawableList.add(sprite.getDrawable(new Point(400,300)));
		if(d!=null)
		{
			drawablePlayer = d;
		}
	}
	/**
	 * adds the drawable item representing a character's stats in the format
	 * img: character face
	 * Point.getX: percentage of current health. Displayed as a float, 1 max
	 * Point.getY: percentage of current EP. Displayed as a float, 1 max
	 * angle: rage points. Every pi/4 (45 degrees) represents 1 full rage point.
	 * @param d the drawable object
	 */
	public void addStats(Drawable d)
	{
		drawableStats.add(d);
	}
	/**
	 * adds a list of stat drawable objects, with the same format as addStats(Drawable d)
	 * @param d list of drawable Objects
	 */
	public void addStats(LinkedList<Drawable> d)
	{
		drawableStats.addAll(d);
		
	}
	/**
	 * gets Drawable stat objects, making sure to return the player last
	 * @return list of drawable objects
	 */
	public LinkedList<Drawable> getDrawableStats()
	{
		LinkedList<Drawable> ans = new LinkedList<Drawable>();
		ans.addAll(drawableStats);
		drawableStats.clear();
		return ans;
	}
	/**
	 * used by DBComm, sets the center of the screen to a certain position
	 * @param p center of the screen(player's coordinates)
	 */
	public void setCenter(Point p)
	{
		this.center = p;
	} 
	/**
	 * sends a text message to be displayed in the game, NOT IN THE CHAT
	 * @param str
	 */
	public void sendMsg(String str){
		display.displayMsg(str);
	}
	/**
	 * sends a text message to be displayed in the game, NOT IN THE CHAT
	 * and will also shut down the game within a few seconds
	 * @param str
	 */
	public void sendFatalMsg(String str){
		display.displayFatalMsg(str);
	}
	/**
	 * sends a chat message to DBComm. The actual message isn't sent
	 * until the game's start() loop sends out the full package of actions
	 * for this clock cycle
	 * @param str the chat message
	 */
	public void sendChat(String str)
	{
		this.chat = str;
	}
	/**
	 * sends a chat message to the typing panel to be displayed
	 * @param str chat message
	 */
	public void receiveChat(String str)
	{
		display.receiveChat(str);
	}
	/**
	 * sets all variables to let game know the character
	 * is pressing the up key
	 */
	public void pressedUp()
	{
		up = true;
	}
	/**
	 * sets all variables to let game know the character
	 * is pressing the down key
	 */
	public void pressedDown()
	{
		down = true;
	}
	public void pressedLeft()
	{
		left = true;
	}
	public void pressedRight()
	{
		right = true;
	}
	/**
	 * sets all variables to let game know the character
	 * is pressing the space key
	 */
	public void pressedSpace()
	{
		space = true;
	}
	public void pressedB()
	{
		B = true;
	}
	public void releasedRight()
	{
		right = false;
	}
	public void releasedLeft()
	{
		left = false;
	}
	public void releasedUp()
	{
		up = false;
	}
	public void releasedDown()
	{
		down = false;
	}
	public void releasedSpace()
	{
		space = false;
	}
	public void releasedB()
	{
		B = false;
	}

}